//
//  ALHomeTableViewController.swift
//  ALSinaWeiBoSwift
//
//  Created by 柴瑞军 on 16/4/8.
//  Copyright © 2016年 myCompany. All rights reserved.
//

import UIKit
import SVProgressHUD
import SVPullToRefresh

class ALHomeTableViewController: ALBaseTableViewController {
    private let identifier = "cell"

    var userDatas:[ALStatus]?{
        didSet{
        //每当模型的数据发生改变的时候就刷新tableView
//            ALPrint("总的微博数据\(userDatas?.count)")
        tableView.reloadData()
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 用户没有登录不需要做一下操作
        if !ALUserAccountViewModel.userAccountViewModel.userLogin {
            ALPrint("没有登录不做一下操作")
            return
        }
        setupNavigationBar()

        prepareTableView()
        
    }
    private func prepareTableView(){
        
        tableView.addSubview(pullDownRefresh)
        
        //cell的tableView的预估行高是在view显示之前给view给定一个行高,具体的行高是在cell进行显示的时候确定
        
//        tableView.estimatedRowHeight = 2
        tableView.rowHeight = UITableViewAutomaticDimension
        
        //        取消分割线
        tableView.separatorStyle = UITableViewCellSeparatorStyle.None
        //        注册cell
        tableView.registerClass(ALStatusCell.self, forCellReuseIdentifier: identifier)
        pullDownRefresh.pullDownRefreshHandler = {
            ()->() in
            self.loadNewStatus()
            
        }
        
        // 让控件进入到刷新状态
        pullDownRefresh.startRefreshing()

        
//        //上拉加载更多数据----使用第三放加载更多数据
//        tableView.addInfiniteScrollingWithActionHandler { 
//            //上拉就加载更多的数据
//            ALPrint("上拉加载更多数据")
//            self.loadMoreStatus()
//        }
        
    }
    
    //上拉加载更多数据
    private func loadMoreStatus(){
    //获取最小的微博
        let max_id = self.userDatas?.last?.id ?? 0
        
    //一条数据都没有就不去上拉加载数据
        if max_id == 0 {
            ALPrint("没有数据进行加载")
            return
        }
        
        //加载比max_id更小的数据
ALStausAccountViewModel.sharedInstance.loadStatus(0, max_id: max_id-1) { (statuses, error) in
    //让刷新控件停止刷新
    self.tableView.infiniteScrollingView.stopAnimating()
    if error != nil {
        ALPrint("上拉刷新加载更多数据失败\(error)")
        return
    }
    
    
    //获取加载数据的数量
    let count = statuses?.count ?? 0
    if count == 0{
    ALPrint("没有更旧的数据可供加载了")
        SVProgressHUD.showErrorWithStatus("没有更旧的数据了")
        return
    }
    
    //有之前的数据可供加载
    //拼接老的数据,将老的数据拼接到现有数据的后面
    let oldStatus = self.userDatas! + statuses!
    
    self.userDatas = oldStatus
//    ALPrint("现有的数据\(oldStatus)---加载了\(count)条数据")
        }
    }
    
    
    //加载新的微博数据
    private func loadNewStatus(){
    //获取ID最大的微博.第一条微博就是Id最大的微博,当地一次进入刷新,一条微博都没有ID= 0,加载最新的20条
        let since_id = self.userDatas?.first?.id ?? 0
      //加载了数据,准备了数据包传递给了加载数据的的回掉方法
    ALStausAccountViewModel.sharedInstance.loadStatus(since_id, max_id: 0) { (statuses, error) in
        //加载数据完成了让控件完成刷新
        self.pullDownRefresh.endRefreshing()
        
        if error != nil{
        ALPrint("微博获取数据失败")
            SVProgressHUD.showErrorWithStatus("您的网络不给力")
            return
        }
        
//       判断返回微博数据的数量
        
        let count = statuses?.count ?? 0
        //如果是第一次加载微博数据,则不需要显示数据的提醒
        if since_id != 0{
            self.showTipLabel(count)
        }
        if count == 0 {
//        ALPrint("没有加载到网络数据")
            if since_id == 0{
                SVProgressHUD.showErrorWithStatus("没有加载到网络数据")
            }
            return
        }
        

        
        // 加载微博成功,将微博数据保存起来,让tableView去显示
        // 判断,如果 since_id = 0
        if since_id == 0 {
            self.userDatas = statuses
            // 第一次进来tableView没有数据since_id = 0 ,加载最新20条,有数据后才添加上拉加载更多这个功能
            self.tableView.addInfiniteScrollingWithActionHandler { () -> Void in
                // 上拉加载数据
                self.loadMoreStatus()
            }
        } else {
            // 如果since_id != 0, 将返回的数据拼接到现有数据前面
            // 数组直接使用加号拼接
            let s = statuses! + self.userDatas!
            
            // 将拼接好的数据赋值给self.statuses
            self.userDatas = s
        }

        }
    }
    //显示下拉刷新数据提示
    //count:更新数据的条数
    private func showTipLabel(count: Int){
    
        let label = UILabel(fontSize: 14, textColor: UIColor.whiteColor())
        let TipLabelHeight: CGFloat = 44
        label.backgroundColor = UIColor.orangeColor()
        label.textAlignment = NSTextAlignment.Center
        
//        将label添加到导航栏中 : y = -(导航栏的高度 + 自己的高度)
       let  y = -(UIApplication.sharedApplication().statusBarFrame.height + TipLabelHeight)
        //label的frame
        
        label.frame = CGRectMake(0, y, UIScreen.mainScreen().bounds.width, TipLabelHeight)
        
        //设置微薄的内容
//        ALPrint("加载了\(count)")
        label.text = count == 0 ? "没有最新的微博数据":"下拉刷新了\(count)条微博数据"
        
        
        //添加到导航栏上面
        navigationController?.navigationBar.insertSubview(label, atIndex: 0)
        
        //label动画
        UIView.animateWithDuration(alDefaultTimeInterval, animations: { 
            //uiview动画放过来执行
//            UIView.setAnimationRepeatAutoreverses(true)
            //uiview动画重复执行
//            UIView.setAnimationRepeatCount(3)
            
            //改变label的frame
            label.frame = CGRect(x: 0, y: TipLabelHeight, width: UIScreen.mainScreen().bounds.width, height: TipLabelHeight)
            }) { (_) in
                //停顿一会在回到屏幕的上面去
                UIView.animateWithDuration(alDefaultTimeInterval, delay: 0.5, options: [], animations: { 
                    //重新改变frame的值
                    label.frame = CGRect(x: 0, y: y, width: UIScreen.mainScreen().bounds.width, height: TipLabelHeight)
                    }, completion: { (_) in
                        //将创建的label从navgationbar上移除
                        ALPrint("动画完成了")
                        label.removeFromSuperview()
                })
        }
    }
    
//懒加载下拉刷新控件
    private lazy var pullDownRefresh: ALPullDownRefreshControl = ALPullDownRefreshControl()
    
 
    private func setupNavigationBar(){
        
        // 设置导航控制器的左右按钮
        navigationItem.leftBarButtonItem = UIBarButtonItem(imageNamed: "navigationbar_friendsearch", target: self, action: #selector(ALHomeTableViewController.didClickPerson(_:)))
        
        // 右边
        navigationItem.rightBarButtonItem = UIBarButtonItem(imageNamed: "navigationbar_pop", target: self, action: #selector(ALHomeTableViewController.didClickQRCode(_:)))
        
        
        //        设置导航条的titleView
        let name = ALUserAccountViewModel.userAccountViewModel.userAccount?.screen_name ?? "没有名称"
        let button = ALHomeTitleButton(title: name)
        
        //        监听的方法
        button.addTarget(self, action: #selector(ALHomeTableViewController.didClickTitleBtn(_:)), forControlEvents: UIControlEvents.TouchUpInside)
        navigationItem.titleView = button
    }
    
    @objc private func didClickTitleBtn(button:UIButton){
       button.selected = !button.selected
//        动画旋转图片
        UIView.animateWithDuration(1) {
          button.imageView?.transform =  button.selected ? CGAffineTransformMakeRotation(CGFloat(M_PI)-0.0001) : CGAffineTransformIdentity
        }
        
//      print("titleBtn:\(button)")
    }
    @objc private func didClickPerson(button:UIButton){
     ALPrint("home:点击了添加联系人按钮")
    }
    @objc private func didClickQRCode(button:UIButton){
        ALPrint("home:点击了扫一扫按钮")
    }
}

/*

             tableView优化:
             1.cell重用
             2.dequeueReusableCellWithIdentifier:forIndexPath:(会调用heightForRowAtIndexPath) 和 dequeueReusableCellWithIdentifier (后面这个不会再次调用heightForRowAtIndexPath)
             2.1 tableView在cell显示之前会调用heightForRowAtIndexPath,有多少个cell就会调用多少次, 算contentSize
             2.2 使用了预估行高,并不会再显示之前去计算获取所有的行高,根据预估行高和实际行高来获取cell的行高,先根据预估行高计算好要先获取几个cell,如果计算的这几个cell高度确实够(高度能超出屏幕的高度就不计算了.如果不够还会计算),目的也是让contentSize大于屏幕,就能滚动,后面要显示,才来计算行高, 会发现滚动条会跳
             3.cell的高度是根据内容变化的时候,只计算一次,将高度缓存起来
             4.下载图片使用SDWebImage(异步操作)
             5.cellForRowAtIndexPath不要做耗时操作
             1.读取文件,写入文件,最好是放到子线程,或先读取好,在让tableView去显示
             2.解压资源
             3.尽量少得计算计算,最好是先计算好,cellForRowAtIndexPath只做显示
             4.尽量不要去添加和移除view, 现将会用到的控件懒加载,要就显示,不要就隐藏
             6.tableView滚动的时候,不要去做动画
             7.cell里面的控件,约束最好不要使用remake,动态添加约束是比较耗性能的
             8.cell里面的控件,背景最好是不透明的 (图层混合), view的背景颜色 clearColor 尽量少
             9.图片圆角不要使用 layer.cornerRadius
             10.图层最好不要使用阴影, 阴影会导致离屏渲染
             11.异步绘制
             12.栅格化
             13.AsyncDisplayKit -> 不使用UIKit (UIView) ->  (Node)
             14.借助工具来测试性能
 
 **/

//实现代理方法
extension ALHomeTableViewController{
    
    /**
     在考虑到tableView的优化的时候,rowHeight的计算最好不要设置预设行高,我们应该在代理方法中计算行高
     
     当给tableView给定预估行高的时候,具体的行高会在cell进行展示的时候才去确定具体的值
     
     */
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
       //在模型中定义cellHeight的属性,
        //获取模型
        let status = self.userDatas![indexPath.row]
        //判断模型中有没有之前缓存过的行高
        if  (status.rowHeight != nil) {
            //存缓存中获取cell的rowheight
            return status.rowHeight!
        }
        
        //如果缓存中没有的还自己在去cell中获取
        let cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! ALStatusCell
        
        cell.status = status
        
        //我们目的是在cell中获得cell的行高,根据view的大小获取行高
        let  rowHeight = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        //将行高的数据保存到模型的中
        status.rowHeight = rowHeight
        
//        ALPrint("cell的行高是:\(rowHeight),对应的行是:\(indexPath.row)")
        
        return rowHeight
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return userDatas?.count ?? 0
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

//        方法一:
//        let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! ALStatusCell
//       方法二:
        let cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! ALStatusCell
        //相比oc的不同点是不做下面的判断赋值
//        if cell == nil {
//            cell = ALStatusCell.init(style: UITableViewCellStyle.Default, reuseIdentifier: identifier)
//        }
//        cell.textLabel?.text = self.userDatas![indexPath.row].text
        cell.status = self.userDatas?[indexPath.row]
        return cell
    }
    
//    cell不要高亮---建议使用这种方法,而不是使用下面的方法
    override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        return false
    }


}